import math
import threading
import time

import cv2
from numba import njit, jit
import mediapipe as mp
import globals

mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_holistic = mp.solutions.holistic
holistic = mp_holistic.Holistic(
    static_image_mode=False,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5)
#cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

# 最大线程数
sem = threading.Semaphore(10)


# @njit
def vector_2d_angle(v1, v2):
    '''
        求解二维向量的角度
    '''
    v1_x = v1[0]
    v1_y = v1[1]
    v2_x = v2[0]
    v2_y = v2[1]
    try:
        angle_ = math.degrees(math.acos(
            (v1_x * v2_x + v1_y * v2_y) / (((v1_x ** 2 + v1_y ** 2) ** 0.5) * ((v2_x ** 2 + v2_y ** 2) ** 0.5))))
    except:
        angle_ = 65535.
    if angle_ > 180.:
        angle_ = 65535.
    return angle_


# @njit
def hand_angle(hand_):
    '''
        获取对应手大拇指相关向量的二维角度,根据角度确定手势
    '''
    #
    angle_ = vector_2d_angle(
        ((int(hand_[0][0]) - int(hand_[2][0])), (int(hand_[0][1]) - int(hand_[2][1]))),
        ((int(hand_[3][0]) - int(hand_[4][0])), (int(hand_[3][1]) - int(hand_[4][1])))
    )
    return angle_


# @njit
def standardizationXY(x, y, bg_size):
    x = x + ((x - bg_size[0] // 2) * 0.6)
    y = y + ((y - bg_size[1] // 2) * 0.7)
    # 降低精度，防抖动
    x = int(x * 10) / 10
    y = int(y * 10) / 10

    # 防超屏
    if y > bg_size[1] - 60:
        y = bg_size[1] - 60
    if x > bg_size[0] - 40:
        x = bg_size[0] - 40
    if x < -60:
        x = -60
    return x, y


def getHandLocal(RHL, image):
    hand_local = []
    for i in range(5):
        v1 = RHL.landmark[i].x * image.shape[1]
        v2 = RHL.landmark[i].y * image.shape[0]
        hand_local.append((v1, v2))
    return hand_local


def get_hand_coord(bg_size, enemy_group, bomb_sound) -> (float, float):
    x, y = None, None
    with sem:
        success, image = cap.read()
        if not success: return
        results = holistic.process(image)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        image.flags.writeable = False
        if results.left_hand_landmarks:
            RHL = results.left_hand_landmarks
            x = bg_size[0] - RHL.landmark[12].x * bg_size[0]
            y = RHL.landmark[0].y * bg_size[1]

        elif results.right_hand_landmarks:
            RHL = results.right_hand_landmarks
            x = bg_size[0] - RHL.landmark[12].x * bg_size[0]
            y = RHL.landmark[0].y * bg_size[1]

        # 灵敏度调整(确保手掌靠近摄像头中心)
        if x is not None and y is not None:
            x, y = standardizationXY(x, y, bg_size)

        if results.left_hand_landmarks or results.right_hand_landmarks:
            hand_local = getHandLocal(RHL,image)
            angle = int(hand_angle(hand_local))
            if angle > 70:  # 多轮测试，70-80比较合适
                kill_all_enemy(enemy_group, bomb_sound)
            print("\r【相对坐标】x：", x, " -- y:", y,"【大拇指弯曲角度】",angle,"°",end="")
    return x, y


last_call_time = None


def kill_all_enemy(enemy_group, bomb_sound):
    """
    销毁所有敌机
    :param enemy_group: 敌机组
    :param bomb_sound: 爆炸音效
    :return:
    """
    global last_call_time
    now = time.time()
    if last_call_time is None or now - last_call_time >= 3:  # 防止连续释放
        last_call_time = now
        if globals.get_bomb_num() > 0:
            bomb_sound.play()
            if not globals.get_invincible:
                globals.use_bomb()
            for e in enemy_group:
                if e.rect.bottom > 0:
                    e.active = False
